<?php
//
namespace handle\message\lib;

use auxiliary\traits\Singleton;
use Exception;
use handle\message\lib\base\MainCenter;
use handle\message\lib\driver\EventDriver;
use handle\message\lib\factory\SingletonFactory;
use handle\message\lib\socket\SocketHandler;
use Workerman\Connection\TcpConnection;


class Entrance extends MainCenter
{
    use Singleton;
    /**
     * Socket连接器
     * @var TcpConnection
     */
    protected TcpConnection $connection;

    /**
     * 事件驱动器
     * @var EventDriver
     */
    private EventDriver $event;

    /**
     * 重启后恢复数据
     * @var bool
     */
    private bool $restartRecovery = true;

    /**
     * 设置玩家连接器
     * @param TcpConnection $connection
     * @return void
     */
    public function setConnection(TcpConnection $connection): void
    {
        $this->connection = $connection;
    }

    /**
     * 启动方法
     * @return void
     */
    public function startupMethod(): void
    {
        try {
            if($this->isSign){
                if(!in_array($this->mode, ['heartbeat'])){
                    if((empty($this->data['uid']) or empty($this->data['room_id']))){
                        workerLog('/entrance', '缺少必要参数' . json_encode($this->data));
                        $this->responseError('参数错误');
                        return;
                    }
                    $this->connection->uid = $this->data['uid'];
                    empty($this->event) and $this->event = SingletonFactory::getInstance()->makeInstances('event');
                    if($this->restartRecovery){
                        $this->restartRecovery = false;
                        $this->event->restore($this->data['room_id']);
                    }
                }
                $this->{$this->mode}();
            }
        }catch (Exception $e){
            $this->responseError($e->getMessage());
        }
    }

    /**
     * 后台操作-关闭房间
     * @return void
     */
    private function systemCloseRoom(){
        try {
            SingletonFactory::getInstance()->makeInstances('system')->setConnection(new SocketHandler($this->connection));
            $this->event->systemCloseRoom($this->data['room_id']);
        }catch (Exception $e){
            $this->responseError($e->getMessage());
        }
    }

    /**
     * 后台操作-关闭棋局
     * @return void
     */
    private function systemEndGame(){
        try {
            SingletonFactory::getInstance()->makeInstances('system')->setConnection(new SocketHandler($this->connection));
            $this->event->systemEndGame($this->data['room_id']);
        }catch (Exception $e){
            $this->responseError($e->getMessage());
        }
    }

    /**
     * 创建房间
     * @return void
     */
    private function createRoom(): void
    {
        try {
            $this->event->checkRoomIsset($this->data['room_id']) ? $this->connection->send(sendMsg('房间已经存在，不可重复创建')) : $this->event->create($this->data['room_id']);
        }catch (Exception $e){
            $this->responseError($e->getMessage());
        }
    }

    /**
     * 进入房间
     * @return void
     */
    private function enterRoom(): void
    {
        try {
            if(!$this->event->checkRoomIsset($this->data['room_id'])) {
                $this->connection->send(sendMsg('房间不存在，不可进入'));
                return;
            }
            if(!($this->event->getManager('player')->checkPlayerIsset($this->data['room_id'], $this->data['uid']))){ //正常进入房间
                $this->event->createPlayer($this->data['room_id'], $this->data['uid'], $this->data['name'], $this->data['homeowner'])->setConnection(new \handle\message\lib\socket\SocketHandler($this->connection));
                $this->event->enterRoom($this->data['room_id'], $this->data['uid']);
            }else{  //已经进入了房间，算做重新连接(情况：当前页面刷新/外部重新连接，这两种操作都会重新连接上socket从而创建一个新的连接，所以需要覆盖之前的连接，并关闭之前的连接)
                $this->resetConnection();
                $this->event->reconnect($this->data['room_id'], $this->data['uid']);
            }
        }catch (Exception $e){
            $this->responseError($e->getMessage());
        }
    }

    /**
     * 重置连接
     * @return void
     */
    private function resetConnection(): void
    {
        try {
            $this->event->getManager('player')->checkPlayerIsset($this->data['room_id'], $this->data['uid']) and $this->event->createConnection($this->data['room_id'], $this->data['uid'], new \handle\message\lib\socket\SocketHandler($this->connection));
        }catch (Exception $e){
            $this->responseError($e->getMessage());
        }
    }

    /**
     * 退出房间
     * @return void
     */
    private function exitRoom(): void
    {
        try {
            $this->event->checkRoomIsset($this->data['room_id']) ? $this->event->exitRoom($this->data['room_id'], $this->data['uid']) : $this->connection->send(sendMsg('房间不存在/已经关闭'));
        }catch (Exception $e){
            $this->responseError($e->getMessage());
        }
    }

    /**
     * 开始游戏
     * @return void
     */
    private function startGame(): void
    {
        try {
            if(!$this->event->getManager('room')->isCanStartGame($this->data['room_id'])){
                $this->connection->send(sendMsg('人数不足两人，不可以开始游戏'));
                return;
            }
            $this->event->createChessBoard($this->data['room_id']);
            $this->event->startGame($this->data['room_id'], $this->data['uid']);
        }catch (Exception $e){
            $this->responseError($e->getMessage());
        }
    }

    /**
     * 更新玩家信息
     * @return void
     */
    private function updatePlayer(): void
    {
        try {
            $this->data['chess'] = (!isset($this->data['chess']) or !is_numeric($this->data['chess'])) ? 0 : $this->data['chess'];
            $this->event->getManager('room')->getRoomStatus($this->data['room_id']) === 0 ? $this->event->updatePlayer($this->data['room_id'], $this->data['uid'], $this->data['chess'], $this->data['chess'] === 1 ? 1 : 2) : $this->connection->send(sendMsg('只能在未开始游戏时才能执行操作'));
        }catch (Exception $e){
            $this->responseError($e->getMessage());
        }
    }

    /**
     * 更新棋盘
     * @return void
     */
    private function updateBoard(): void
    {
        try {
            $this->event->getManager('room')->getRoomStatus($this->data['room_id']) === 1 ?
                $this->event->getManager('player')->isMyTurn($this->data['room_id'], $this->data['uid']) ?
                    $this->event->updateBoard($this->data['room_id'], $this->data['x'], $this->data['y'], $this->data['uid'])
                : $this->connection->send(sendMsg('不是你的回合，不可落子'))
            : $this->connection->send(sendMsg('游戏尚未开始/已经结束，不可落子'));
        }catch (Exception $e){
            $this->responseError($e->getMessage());
        }
    }

    /**
     * 发送请求消息
     * @return void
     */
    private function sendRequest(): void
    {
        try {
            $this->event->getManager('room')->getRoomStatus($this->data['room_id']) === 1 ? $this->event->sendRelatedRequest($this->data['room_id'], $this->data['uid'], $this->data['type']) : $this->connection->send(sendMsg('游戏尚未开始/已经结束，不可执行操作'));
        }catch (Exception $e){
            $this->responseError($e->getMessage());
        }
    }

    /**
     * 发送拒绝通知给对方
     * @return void
     */
    private function sendRefuseNotify(): void
    {
        try {
            $this->event->getManager('room')->getRoomStatus($this->data['room_id']) === 1 ? $this->event->sendRefuseNotify($this->data['room_id'], $this->data['uid'], $this->data['type']) : $this->connection->send(sendMsg('游戏尚未开始/已经结束，不可执行操作'));
        }catch (Exception $e){
            $this->responseError($e->getMessage());
        }
    }

    /**
     * 悔棋
     * @return void
     */
    private function withdraw(): void
    {
        try {
            $this->event->getManager('room')->getRoomStatus($this->data['room_id']) === 1 ? $this->event->withdraw($this->data['room_id'], $this->data['uid']) : $this->connection->send(sendMsg('游戏尚未开始/已经结束，不可执行操作'));
        }catch (Exception $e){
            $this->responseError($e->getMessage());
        }
    }

    /**
     * 求和
     * @return void
     */
    private function gameTie(): void
    {
        try {
            $this->event->getManager('room')->getRoomStatus($this->data['room_id']) === 1 ? $this->event->gameTie($this->data['room_id'], $this->data['uid']) : $this->connection->send(sendMsg('游戏尚未开始/已经结束，不可执行操作'));
        }catch (Exception $e){
            $this->responseError($e->getMessage());
        }
    }

    /**
     * 认输
     * @return void
     */
    private function surrender(): void
    {
        try {
            $this->event->getManager('room')->getRoomStatus($this->data['room_id']) === 1 ? $this->event->surrender($this->data['room_id'], $this->data['uid']) : $this->connection->send(sendMsg('游戏尚未开始/已经结束，不可执行操作'));
        }catch (Exception $e){
            $this->responseError($e->getMessage());
        }
    }

    /**
     * 心跳包
     * @return void
     */
    private function heartbeat(){
        $this->connection->lastMessageTime = time();
        workerLog('/heartbeat', '心跳');
    }

    public function __call($name, $arguments): void
    {
        // TODO: Implement __call() method.
        $this->connection->send(sendMsg('请求错误'));
        workerError('请求错误：' . $name . '，参数：' . json_encode($arguments), '/function');
    }

}